// Mechanicoder
// 2023/02/19

#include "view_window.h"
#include "View.h"
#include "ui_ctrl_widget.h"
#include "algo_inspect_brepfill_filling.h"
#include "algo_inspect_GeomPlate_BuildPlateSurface.h"

#include <STEPControl_Reader.hxx>
#include <STEPControl_Writer.hxx>
#include <Graphic3d_ArrayOfPoints.hxx>
#include <AIS_Shape.hxx>
#include <AIS_PointCloud.hxx>
#include <AIS_InteractiveObject.hxx>
#include <Prs3d_PointAspect.hxx>
#include <Prs3d_Drawer.hxx>
#include <Graphic3d_AspectFillArea3d.hxx>
#include <BRepOffsetAPI_MakeOffset.hxx>
#include <BRepBuilderAPI_MakeVertex.hxx>
#include <BRepBuilderAPI_MakeWire.hxx>
#include <BRepBuilderAPI_MakeFace.hxx>
#include <BRepBuilderAPI_Transform.hxx>
#include <BRepBuilderAPI_MakePolygon.hxx>
#include <BRepBuilderAPI_Copy.hxx>
#include <BRepLib.hxx>
#include <BRepBndLib.hxx>
#include <BRep_Tool.hxx>
#include <BRep_Builder.hxx>
#include <ShapeAnalysis.hxx>
#include <TopoDS.hxx>
#include <TopoDS_Wire.hxx>
#include <TopExp.hxx>
#include <TopExp_Explorer.hxx>
#include <Standard_Version.hxx>
#include <AIS_InteractiveContext.hxx>
#include <BRepFill_Filling.hxx>
#include <ShapeFix_Face.hxx>
#include <Quantity_Color.hxx>
#include <Bnd_OBB.hxx>
#include <Geom2dAPI_Interpolate.hxx>
#include <Geom2d_BSplineCurve.hxx>
#include <Geom_BSplineSurface.hxx>

#include <QHBoxLayout>
#include <QFileDialog>
#include <QDebug>
#include <QLineEdit>
#include <QKeyEvent>
#include <QMessageBox>
#include <QTimer>

namespace
{
    void TestPeriodic()
    {
        gp_Pnt2d p1(0, 0);
        gp_Pnt2d p2(0, 10);
        gp_Pnt2d p3(5, 5);
        Handle(TColgp_HArray1OfPnt2d) pnts = new TColgp_HArray1OfPnt2d(1, 3);
        pnts->SetValue(1, p1);
        pnts->SetValue(2, p2);
        pnts->SetValue(3, p3);
        Geom2dAPI_Interpolate interp(pnts, true, Precision::Confusion());
        interp.Perform();
        if (!interp.IsDone())
        {
            qDebug() << "插值失败";
        }

        Handle(Geom2d_BSplineCurve) bc = interp.Curve();
        std::vector<double> flat_knots(bc->KnotSequence().begin(), bc->KnotSequence().end());
        std::vector<gp_Pnt2d> ctrl_pnts(bc->NbPoles());
        for (size_t i = 0; i < ctrl_pnts.size(); i++)
        {
            ctrl_pnts[i] = bc->Pole(int(i + 1));
        }
        const int degree = bc->Degree();
        qDebug() << "Degree " << degree;
        qDebug() << "Flat Knots " << flat_knots;
    }

    std::vector<std::vector<gp_Pnt>> MakeSurfGridPnts(const Handle(Geom_Surface)& surf)
    {
        if (surf)
        {
            Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf);
            if (bs)
            {
                if (bs->IsVPeriodic())
                {
                    std::vector<std::vector<gp_Pnt>> all_pnts;
                    double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
                    bs->Bounds(u1, u2, v1, v2);
                    const size_t N = 20;
                    for (size_t j = 0; j < N; j++)
                    {
                        double v = v1 + (v2 - v1) * double(j) / double(N - 1);
                        std::vector<gp_Pnt> pnts;
                        for (size_t i = 0; i < N; i++)
                        {
                            double u = u1 + (u2 - u1) * double(i) / double(N - 1);
                            pnts.emplace_back(bs->Value(u, v));
                        }
                        all_pnts.emplace_back(pnts);
                    }

                    return all_pnts;
                }
            }
        }
        return {};
    }

    TopoDS_Shape Compound(const std::vector<TopoDS_Shape>& shapes)
    {
        TopoDS_Compound comp;
        BRep_Builder builder;
        builder.MakeCompound(comp);
        for (const auto& s : shapes)
        {
            if (!s.IsNull())
            {
                builder.Add(comp, s);
            }
        }
        return comp;
    }

    TopoDS_Shape MakeGridShape(const std::vector<std::vector<gp_Pnt>>& all_pnts)
    {
        std::vector<TopoDS_Shape> polys;
        for (const auto& pnts : all_pnts)
        {
            BRepBuilderAPI_MakePolygon poly;
            for (const auto& p : pnts)
            {
                poly.Add(p);
            }
            polys.emplace_back(poly.Shape());
        }
        return Compound(polys);
    }

    void TestSetOrigin(const std::vector<TopoDS_Shape>& selected, ModelList* ml)
    {
        TopoDS_Face face;
        for (const auto& f : selected)
        {
            if (!f.IsNull() && TopAbs_FACE == f.ShapeType())
            {
                face = TopoDS::Face(f);
            }
        }

        Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
        if (surf)
        {
            Handle(Geom_BSplineSurface) bs = Handle(Geom_BSplineSurface)::DownCast(surf);
            if (bs->IsVPeriodic())
            {
                auto all_pnts = MakeSurfGridPnts(bs);
                if (!all_pnts.empty())
                {
                    TopoDS_Shape pnts_shape = MakeGridShape(all_pnts);
                    ml->RecordModel(pnts_shape, "Before");
                }

                double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
                bs->Bounds(u1, u2, v1, v2);
                bs->SetVOrigin((bs->FirstVKnotIndex() + bs->LastVKnotIndex()) / 2);

                all_pnts = MakeSurfGridPnts(bs);
                if (!all_pnts.empty())
                {
                    TopoDS_Shape pnts_shape = MakeGridShape(all_pnts);
                    ml->RecordModel(pnts_shape, "After");
                }
            }
        }
    }

}

struct ViewWindow::Data
{
    Handle(AIS_InteractiveContext) context;

    View* view;
    Ui::CtrlWidgetUi* ctrlUi;

    std::vector<Handle(AIS_InteractiveObject)> generated;

    gp_XYZ bndCenter; // 边界中心

    bool surfDeformRunning;
    std::vector<gp_Pnt2d> surfDeformUVs;
    std::vector<double> surfDeformOffsets;
    std::vector<double> surfDeformOffsetSigns;
    double surfDeformMaxOffset;
};

ViewWindow::ViewWindow(QWidget* parent)
    : QMainWindow(parent), _d(std::make_shared<Data>())
{
    _d->context = ViewHelper::InitContext(ViewHelper::InitViewer());
    _d->view = new View({ _d->context }, this);
    _d->surfDeformRunning = false;

    _d->view->top();

    this->setCentralWidget(_d->view);

    InitCtrlWidget();

    this->resize(800, 600);

    DrawShape(ViewHelper::MakeBottle(80, 100, 20), "Bottle");

    TestPeriodic();
}

ViewWindow::~ViewWindow()
{
}

void ViewWindow::OnImport()
{
    QString filename;
    filename = QFileDialog::getOpenFileName(this, "Select STEP file", "", "*.stp");
    QFileInfo info(filename);
    if (!info.exists())
    {
        return;
    }

    // Clear All
    _d->ctrlUi->listViewDisplay->Clear();

    STEPControl_Reader reader;
    TCollection_AsciiString  aFilePath = filename.toUtf8().data();
    IFSelect_ReturnStatus status = reader.ReadFile(aFilePath.ToCString());

    int nbr = reader.NbRootsForTransfer();
    for (Standard_Integer n = 1; n <= nbr; n++)
    {
        reader.TransferRoot(n);
    }

    // 显示模型
    int nbs = reader.NbShapes();
    for (int i = 1; i <= nbs; i++)
    {
        TopoDS_Shape shape = reader.Shape(i);
        Handle(AIS_Shape) ais = new AIS_Shape(shape);
        _d->ctrlUi->listViewDisplay->RecordModel(ais, QString("Import %1").arg(i));
    }
    _d->view->fitAll();

    _d->context->Activate(ViewHelper::SM_FACE);
    _d->context->Activate(ViewHelper::SM_EDGE);
    _d->context->SetIsoNumber(3);
    _d->view->top();
}

void ViewWindow::OnHideShape()
{
    AIS_ListOfInteractive objs;
    _d->context->ErasedObjects(objs);
    if (objs.IsEmpty())
    {
        _d->context->EraseAll(true);
    }
    else
    {
        _d->context->DisplayAll(true);
    }
}

void ViewWindow::OnNSideFill()
{
    //TestSetOrigin(_d->ctrlUi->widgetBndEdges->GetShapes(), _d->ctrlUi->listViewDisplay);

    TopoDS_Face result_face = MakeNSideFace();

    if (!result_face.IsNull())
    {
        const std::vector<TopoDS_Shape>& selected = _d->ctrlUi->widgetBndEdges->GetShapes();

        Handle(Geom_Surface) surf = BRep_Tool::Surface(result_face);
        TopoDS_Wire outwire = ShapeAnalysis::OuterWire(result_face);
        TopoDS_Face new_face = BRepBuilderAPI_MakeFace(surf, Precision::Confusion());
        DrawShape(result_face, QString("N 边面-原始-边数量 %1").arg(selected.size()), Quantity_NOC_GREEN);
        DrawShape(outwire, QString("N 边面-边界-边数量 %1").arg(selected.size()), Quantity_NOC_GREEN);
        DrawShape(new_face, QString("N 边面-去掉边界-边数量 %1").arg(selected.size()), Quantity_NOC_GREEN);
    }
}

void ViewWindow::OnSurfPntChanged()
{
    if (!_d->ctrlUi->widgetSurfPnt->GetShapes().empty())
    {
        TopoDS_Vertex surf_vertex;
        TopoDS_Face face = MakeNSideFace(nullptr, &surf_vertex);
        _d->ctrlUi->listViewDisplay->Preview("SurfacePntChanged_NFace", face, Quantity_NOC_GREEN);
        _d->ctrlUi->listViewDisplay->Preview("SurfacePntChanged_Pnt", surf_vertex, Quantity_NOC_RED);
    }
    else
    {
        _d->ctrlUi->listViewDisplay->Preview("SurfacePntChanged_NFace", TopoDS_Shape());
        _d->ctrlUi->listViewDisplay->Preview("SurfacePntChanged_Pnt", TopoDS_Shape());
    }
}

void ViewWindow::OnFreePntEnabled()
{
    if (_d->ctrlUi->groupBoxFreePnt->isChecked())
    {
        _d->bndCenter = CalcBoundaryCenter().XYZ();

        OnFreePntChanged();
    }
    else
    {
        // 清空
        _d->ctrlUi->listViewDisplay->Preview("FreePntCS_NFace", TopoDS_Shape(), Quantity_NOC_GREEN);
        _d->ctrlUi->listViewDisplay->Preview("FreePntCS_Pnt", TopoDS_Shape(), Quantity_NOC_GREEN);
    }
}

void ViewWindow::OnFreePntChanged()
{
    if (_d->ctrlUi->groupBoxFreePnt->isChecked())
    {
        TopoDS_Vertex free_vertex;
        TopoDS_Face free_pnt_face = MakeNSideFace(&free_vertex, nullptr);
        _d->ctrlUi->listViewDisplay->Preview("FreePntCS_NFace", free_pnt_face, Quantity_NOC_GREEN);
        _d->ctrlUi->listViewDisplay->Preview("FreePntCS_Pnt", free_vertex, Quantity_NOC_RED);
    }
}

void ViewWindow::OnContinuityChanged()
{
    if (_d->ctrlUi->groupBoxFreePnt->isChecked())
    {
        OnFreePntChanged();
    }
    else
    {
        OnSurfPntChanged();
    }
}

void ViewWindow::OnSurfDeform()
{
    _d->surfDeformRunning = true;

    _d->surfDeformUVs = { gp_Pnt2d(0.3, 0.3), gp_Pnt2d(0.7, 0.3), gp_Pnt2d(0.5, 0.5) };
    _d->surfDeformOffsets = {0, 0, 0};
    _d->surfDeformOffsetSigns = { 1, -1, 1 };
    _d->surfDeformMaxOffset = 20;

    QTimer::singleShot(100000, this, [this]()
        {
            this->_d->surfDeformRunning = false;
        });

    OnStartSurfDeform();
}

void ViewWindow::OnStartSurfDeform()
{
    const std::vector<TopoDS_Shape>& selected = _d->ctrlUi->widgetSurfPnt->GetShapes();
    TopoDS_Face face;
    for (const auto& s : selected)
    {
        if (!s.IsNull() && TopAbs_FACE == s.ShapeType())
        {
            face = TopoDS::Face(s);
            break;
        }
    }
    if (face.IsNull())
    {
        return;
    }

    RandomUpdateSurfDeformData();

    Handle(Geom_Surface) surf = BRep_Tool::Surface(face);
    double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
    surf->Bounds(u1, u2, v1, v2);

    std::vector<gp_Pnt2d> surf_uvs(_d->surfDeformUVs.size());
    for (size_t i = 0; i < _d->surfDeformUVs.size(); i++)
    {
        const double uratio = _d->surfDeformUVs[i].X();
        const double vratio = _d->surfDeformUVs[i].Y();
        surf_uvs[i] = gp_Pnt2d(u1 + uratio * (u2 - u1), v1 + vratio * (v2 - v1));
    }

    std::vector<gp_Pnt> pnts(surf_uvs.size());
    std::vector<TopoDS_Shape> shapes(surf_uvs.size());
    for (size_t i = 0; i < surf_uvs.size(); i++)
    {
        gp_Pnt pnt;
        gp_Vec du, dv;
        surf->D1(surf_uvs[i].X(), surf_uvs[i].Y(), pnt, du, dv);
        gp_Dir n = du.Crossed(dv);

        pnts[i] = pnt.Translated(gp_Vec(n) * _d->surfDeformOffsets[i]);
        shapes[i] = BRepBuilderAPI_MakeVertex(pnts[i]);
    }

    BRepFill_Filling fill;
    fill.LoadInitSurface(face);
    TopExp_Explorer exp(face, TopAbs_EDGE);
    for (; exp.More(); exp.Next())
    {
        fill.Add(TopoDS::Edge(exp.Current()), face, GeomAbs_G1);
    }
    for (const auto& p : pnts)
    {
        fill.Add(p);
    }

    fill.Build();
    if (fill.IsDone())
    {
        _d->ctrlUi->listViewDisplay->Preview("Surf Deform F", fill.Face(), Quantity_NOC_GREEN);
        _d->ctrlUi->listViewDisplay->Preview("Surf Deform V", Compound(shapes), Quantity_NOC_RED);
    }
    else
    {
        qDebug() << "曲面变形失败";
    }

    if (_d->surfDeformRunning)
    {
        QTimer::singleShot(8, this, &ViewWindow::OnStartSurfDeform);
    }
}

void ViewWindow::InitCtrlWidget()
{
    QWidget* parent = this;
    QWidget* widget = new QWidget(parent);

    _d->ctrlUi = new Ui::CtrlWidgetUi;
    _d->ctrlUi->setupUi(widget);
    widget->setAutoFillBackground(true);

    _d->ctrlUi->widgetBndEdges->Setup(_d->context, "Boundary Edges", "Select(E,F,E,F,...)");
    _d->ctrlUi->widgetFreeEdges->Setup(_d->context, "Free Edges", "Select(E,[F],E,[F],...)");
    _d->ctrlUi->widgetSurfPnt->Setup(_d->context, "Surface Point", "Select(E,F,E,F,...)");
    _d->ctrlUi->listViewDisplay->SetupContext(_d->context);

    QHBoxLayout* hlayout = new QHBoxLayout();
    hlayout->addWidget(widget);
    hlayout->addStretch();

    QVBoxLayout* vlayout = new QVBoxLayout(widget);
    vlayout->addLayout(hlayout);
    vlayout->addStretch();

    connect(_d->ctrlUi->pushButton_import, &QPushButton::clicked, this, &ViewWindow::OnImport);
    connect(_d->ctrlUi->pushButtonNSideFill, &QPushButton::clicked, this, &ViewWindow::OnNSideFill);
    connect(_d->ctrlUi->doubleSpinBoxSurfPntU, &QDoubleSpinBox::valueChanged, this, &ViewWindow::OnSurfPntChanged);
    connect(_d->ctrlUi->doubleSpinBoxSurfPntV, &QDoubleSpinBox::valueChanged, this, &ViewWindow::OnSurfPntChanged);
    connect(_d->ctrlUi->groupBoxFreePnt, &QGroupBox::toggled, this, &ViewWindow::OnFreePntEnabled);
    connect(_d->ctrlUi->doubleSpinBoxOffsetX, &QDoubleSpinBox::valueChanged, this, &ViewWindow::OnFreePntChanged);
    connect(_d->ctrlUi->doubleSpinBoxOffsetY, &QDoubleSpinBox::valueChanged, this, &ViewWindow::OnFreePntChanged);
    connect(_d->ctrlUi->doubleSpinBoxOffsetZ, &QDoubleSpinBox::valueChanged, this, &ViewWindow::OnFreePntChanged);
    connect(_d->ctrlUi->spinBoxContinuity, &QSpinBox::valueChanged, this, &ViewWindow::OnContinuityChanged);
    connect(_d->ctrlUi->pushButtonSurfDeform, &QPushButton::clicked, this, &ViewWindow::OnSurfDeform);

    widget->move(1, 1);
    widget->setWindowOpacity(0.6);

    widget->updateGeometry();
    widget->show();
}

void ViewWindow::DrawShape(const TopoDS_Shape& shape, const QString& name, int color/* = -1*/) const
{
    Handle(AIS_Shape) ais = new AIS_Shape(shape);
    if (_d->ctrlUi)
    {
        _d->ctrlUi->listViewDisplay->RecordModel(ais, name, color);
    }
}

bool ViewWindow::IsAllCurve3D(const TopoDS_Shape& shape) const
{
    TopTools_IndexedMapOfShape sub_shapes;
    TopExp::MapShapes(shape, TopAbs_EDGE, sub_shapes); // wire 或 面的外环
    for (auto it = sub_shapes.cbegin(); it != sub_shapes.cend(); ++it)
    {
        TopoDS_Edge edge = TopoDS::Edge(*it);
        double cf = 0;
        double cl = 0;
        Handle(Geom_Curve) c = BRep_Tool::Curve(edge, cf, cl);
        if (!c)
        {
            BRepLib::BuildCurve3d(edge);
            c = BRep_Tool::Curve(edge, cf, cl);
            if (!c)
            {
                return false;
            }
        }
    }
    return true;
}

TopoDS_Face ViewWindow::MakeNSideFace(TopoDS_Vertex* free_vertex/* = nullptr*/,
    TopoDS_Vertex* surf_vertex/* = nullptr*/) const
{
    _d->ctrlUi->labelMsg->setText("");

    try
    {
        const std::vector<TopoDS_Shape>& bnd_edges = _d->ctrlUi->widgetBndEdges->GetShapes();
        if (bnd_edges.size() < 2)
        {
            return TopoDS_Face();
        }
        BRepFill_Filling fill;
        bool valid = false;
        // 边界约束
        for (size_t i = 1; i < bnd_edges.size(); i += 2)
        {
            TopoDS_Shape edge = bnd_edges[i - 1];
            TopoDS_Shape face = bnd_edges[i];
            if (TopAbs_EDGE == edge.ShapeType() && TopAbs_FACE == face.ShapeType())
            {
                // nothing to do
            }
            else if (TopAbs_EDGE == face.ShapeType() && TopAbs_FACE == edge.ShapeType())
            {
                std::swap(edge, face);
            }
            else
            {
                continue;
            }

            fill.Add(TopoDS::Edge(edge), TopoDS::Face(face), GeomAbs_G1);
            valid = true;
        }

        if (!valid)
        {
            qDebug() << "N边面构造错误：输入不符合条件";
            return TopoDS_Face();
        }

        // 非边界约束
        const std::vector<TopoDS_Shape>& free_edges = _d->ctrlUi->widgetFreeEdges->GetShapes();
        for (const auto& fe : free_edges)
        {
            if (TopAbs_EDGE != fe.ShapeType())
            {
                continue;
            }
            TopoDS_Edge e = TopoDS::Edge(fe);
            fill.Add(e, GeomAbs_G1, false);
        }

        // 面上点约束
        const std::vector<TopoDS_Shape>& faces = _d->ctrlUi->widgetSurfPnt->GetShapes();
        for (const auto& fe : faces)
        {
            if (TopAbs_FACE != fe.ShapeType())
            {
                continue;
            }
            TopoDS_Face f = TopoDS::Face(fe);
            Handle(Geom_Surface) surf = BRep_Tool::Surface(f);
            if (!surf)
            {
                continue;
            }
            const double ur = _d->ctrlUi->doubleSpinBoxSurfPntU->value();
            const double vr = _d->ctrlUi->doubleSpinBoxSurfPntV->value();
            double u1 = 0, u2 = 0, v1 = 0, v2 = 0;
            surf->Bounds(u1, u2, v1, v2);
            const double u = u1 + (u2 - u1) * ur;
            const double v = v1 + (v2 - v1) * vr;

            GeomAbs_Shape con;
            switch (_d->ctrlUi->spinBoxContinuity->value())
            {
            case 0: con = GeomAbs_C0; break;
            case 1: con = GeomAbs_G1; break;
            case 2: con = GeomAbs_G2; break;
            default: con = GeomAbs_G1; break;
            }
            fill.Add(u, v, f, con);

            if (surf_vertex)
            {
                *surf_vertex = BRepBuilderAPI_MakeVertex(surf->Value(u, v));
            }
            break;
        }

        // 自由点约束
        if (_d->ctrlUi->groupBoxFreePnt->isChecked())
        {
            gp_XYZ offset(_d->ctrlUi->doubleSpinBoxOffsetX->value(), _d->ctrlUi->doubleSpinBoxOffsetY->value(),
                _d->ctrlUi->doubleSpinBoxOffsetZ->value());
            gp_Pnt pnt = _d->bndCenter + offset;
            fill.Add(pnt);

            if (free_vertex)
            {
                *free_vertex = BRepBuilderAPI_MakeVertex(pnt);
            }
        }

        fill.Build();

        AlgoInspect(fill);

        if (!fill.IsDone())
        {
            qDebug() << "N边面构造错误：Build 异常";
        }

        TopoDS_Face result_face = fill.Face();
        //ShapeFix_Face fix(result_face);
        //if (fix.Perform())
        //{
        //    TopoDS_Shape result = fix.Face();
        //    DrawShape(result, QString("N 边面修复后结果-边数量 ").arg(_selected.size()), Quantity_NOC_GREEN);
        //}
        //else
        return result_face;
    }
    catch (...)
    {
        //QMessageBox::warning(nullptr, QString(__FUNCTION__), "MakeNSideFace 构造失败");
        _d->ctrlUi->labelMsg->setText("N边面构造异常");
        return TopoDS_Face();
    }
}

gp_Pnt ViewWindow::CalcBoundaryCenter() const
{
    const std::vector<TopoDS_Shape>& selected = _d->ctrlUi->widgetBndEdges->GetShapes();
    BRepBndLib bnd;
    Bnd_OBB obb;
    for (size_t i = 1; i < selected.size(); i += 2)
    {
        TopoDS_Shape edge = selected[i - 1];
        TopoDS_Shape face = selected[i];
        if (TopAbs_EDGE == edge.ShapeType() && TopAbs_FACE == face.ShapeType())
        {
            // nothing to do
        }
        else if (TopAbs_EDGE == face.ShapeType() && TopAbs_FACE == edge.ShapeType())
        {
            std::swap(edge, face);
        }
        else
        {
            continue;
        }

        bnd.AddOBB(edge, obb);
    }
    return obb.Center();
}

void ViewWindow::AlgoInspect(const BRepFill_Filling& fill) const
{
    const AI_GeomPlate_BuildPlateSurface* builder =
        (const AI_GeomPlate_BuildPlateSurface*)fill.myBuilder.get();

    Handle(Geom_Surface) init_surf = builder->mySurfInit;
    TopoDS_Face init_face = BRepBuilderAPI_MakeFace(init_surf, Precision::Confusion());
    _d->ctrlUi->listViewDisplay->RecordModel(init_face, "builder->mySurfInit", Quantity_NOC_GRAY);

    const Plate_Plate& plate = builder->myPlate;
}

void ViewWindow::RandomUpdateSurfDeformData() const
{
    for (size_t i = 0; i < _d->surfDeformOffsets.size(); i++)
    {
        int off = std::rand() % 3 + 1;
        double new_offset = _d->surfDeformOffsets[i] + _d->surfDeformOffsetSigns[i] * off;

        if (std::fabs(new_offset) > _d->surfDeformMaxOffset)
        {
            _d->surfDeformOffsetSigns[i] *= -1;
        }

        _d->surfDeformOffsets[i] += _d->surfDeformOffsetSigns[i] * off;
    }

    qDebug() << _d->surfDeformOffsets;
}

void ViewWindow::keyPressEvent(QKeyEvent* event)
{
    /*if (Qt::Key_Up == event->key() ||
        Qt::Key_Down == event->key() ||
        Qt::Key_Left == event->key() ||
        Qt::Key_Right == event->key())
    {
        if (!_pntEnabled)
        {
            _pntEnabled = true;
            _keyX = 0;
            _keyY = 0;
            _keyZ = 0;
        }

        if (Qt::Key_Up == event->key())
        {
            ++_keyZ;
        }
        if (Qt::Key_Down == event->key())
        {
            --_keyZ;
        }
        if (Qt::Key_Left == event->key())
        {
            --_keyX;
            --_keyY;
        }
        if (Qt::Key_Right == event->key())
        {
            ++_keyX;
            ++_keyY;
        }

        TopoDS_Face face = MakeNSideFace();

        if (!_d->keyObj)
        {
            Handle(AIS_Shape) ais = new AIS_Shape(face);
            _d->keyObj = ais;
            _d->context->Display(_d->keyObj, true);
        }
        else
        {
            Handle(AIS_Shape) ais = Handle(AIS_Shape)::DownCast(_d->keyObj);
            if (ais)
            {
                ais->SetShape(face);
            }
            _d->context->Redisplay(ais, true);
        }
    }*/
}
